package com.visitorspecials.tankbattle;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import javax.microedition.khronos.opengles.GL10;

import android.graphics.Bitmap;
import android.opengl.GLUtils;

/*
 * Hi! Welcome to Ye-olde Graphics class! 
 * This class is managed by Dylan Reynolds, and should not be violated by anyone else
 * Trespassers will be shot
 * those still alive will be shot again
 * those found thinking of trespassing will also be shot.
 * 
 * Get off my damn lawn. Ya Yankee scum.
 */
public class Mesh
{
	// Our vertex buffer.
	private FloatBuffer _verticesBuffer = null;

	// Our index buffer.
	private ShortBuffer _indicesBuffer = null;

	// Our UV texture buffer.
	private FloatBuffer _textureBuffer; // New variable.

	// Our texture id.
	private int _textureId = -1; // New variable.

	// The bitmap we want to load as a texture.
	protected Bitmap _bitmap; // New variable.

	protected int[] _textures = new int[1];
	
	// Where are we?
	protected float x, y;

	// The number of indices.
	private int _numOfIndices = -1;

	// Flat Color
	protected final float[] _RGBA = new float[] { 1.0f, 1.0f, 1.0f, 1.0f };

	protected float _heading = 0;

	public void draw(GL10 gl)
	{
		//reset any matrices 
		gl.glLoadIdentity();

		//enable backface culling
		gl.glFrontFace(GL10.GL_CCW);
		gl.glEnable(GL10.GL_CULL_FACE);
		gl.glCullFace(GL10.GL_BACK);

		//turn on vertex array
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glVertexPointer(2, GL10.GL_FLOAT, 0, _verticesBuffer);

		//set BackgroundColor of the mesh
		//gl.glColor4f(_RGBA[0], _RGBA[1], _RGBA[2], _RGBA[3]);

		//loadTexture
		this.loadGLTexture(gl);

		//turn on textures and add its vertices to the texture_vertices buffer
		gl.glEnable(GL10.GL_TEXTURE_2D);
		gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, this._textureBuffer);
		gl.glBindTexture(GL10.GL_TEXTURE_2D, this._textureId);

		//do any rotations
		gl.glTranslatef(x, y, 0);
		gl.glRotatef(_heading, 0, 0, 1);
		gl.glTranslatef(-x, -y, 0);

		//draw the mesh
		gl.glDrawElements(GL10.GL_TRIANGLES, this._numOfIndices,
				GL10.GL_UNSIGNED_SHORT, this._indicesBuffer);

		//disable states that were turned on
		gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		gl.glDisable(GL10.GL_CULL_FACE);
		gl.glDeleteTextures(1, _textures, 0);
	}

	protected void setVertices(float[] vertices)
	{
		// a float is 4 bytes, therefore we multiply the number if
		// vertices with 4.
		ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
		vbb.order(ByteOrder.nativeOrder());
		_verticesBuffer = vbb.asFloatBuffer();
		_verticesBuffer.put(vertices);
		_verticesBuffer.position(0);
	}

	protected void setIndices(short[] indices)
	{
		// short is 2 bytes, therefore we multiply the number if
		// vertices with 2.
		ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
		ibb.order(ByteOrder.nativeOrder());
		_indicesBuffer = ibb.asShortBuffer();
		_indicesBuffer.put(indices);
		_indicesBuffer.position(0);
		_numOfIndices = indices.length;
	}

	protected void setTextureCoordinates(float[] textureCoords)
	{ // New
		// function.
		// float is 4 bytes, therefore we multiply the number if
		// vertices with 4.
		ByteBuffer byteBuf = ByteBuffer
				.allocateDirect(textureCoords.length * 4);
		byteBuf.order(ByteOrder.nativeOrder());
		_textureBuffer = byteBuf.asFloatBuffer();
		_textureBuffer.put(textureCoords);
		_textureBuffer.position(0);
	}

	protected void setColor(float red, float green, float blue, float alpha)
	{
		_RGBA[0] = red;
		_RGBA[1] = green;
		_RGBA[2] = blue;
		_RGBA[3] = alpha;
	}

	public void setBitmap(Bitmap bitmap)
	{ // New function.
		this._bitmap = bitmap;
	}

	private void loadGLTexture(GL10 gl)
	{ // New function
		// Generate one texture pointer...
		gl.glGenTextures(1, _textures, 0);
		_textureId = _textures[0];

		// ...and bind it to our array
		gl.glBindTexture(GL10.GL_TEXTURE_2D, _textureId);

		// Create Nearest Filtered Texture
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
				GL10.GL_LINEAR);
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
				GL10.GL_LINEAR);

		// Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
				GL10.GL_CLAMP_TO_EDGE);
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
				GL10.GL_CLAMP_TO_EDGE);

		// Use the Android GLUtils to specify a two-dimensional texture image
		// from our bitmap
		GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, _bitmap, 0);
	}
}
